package com.ruoyi.system.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.DictConstants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanValidators;
import com.ruoyi.common.utils.security.Md5Utils;
import com.ruoyi.system.domain.EchartsDataset;
import com.ruoyi.system.domain.EvtType;
import com.ruoyi.system.mapper.SysDictDataMapper;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.EvtMapper;
import com.ruoyi.system.domain.Evt;
import com.ruoyi.system.service.IEvtService;
import com.ruoyi.common.core.text.Convert;

/**
 * 事件管理Service业务层处理
 *
 * @author ruoyi
 * @date 2024-08-19
 */
@Service
public class EvtServiceImpl implements IEvtService {
    private static final Logger log = LoggerFactory.getLogger(EvtServiceImpl.class);
    @Autowired
    private EvtMapper evtMapper;

    @Autowired
    private SysDictDataMapper dictDataMapper;
    @Autowired
    private SysDictDataServiceImpl sysDictDataService;
    @Autowired
    private EvtTypeServiceImpl evtTypeService;
    @Autowired
    private SysDeptServiceImpl sysDeptService;

    /**
     * 查询事件管理
     *
     * @param id 事件管理主键
     * @return 事件管理
     */
    @Override
    public Evt selectEvtById(Long id) {
        return evtMapper.selectEvtById(id);
    }

    /**
     * 查询事件管理列表
     *
     * @param evt 事件管理
     * @return 事件管理
     */
    @Override
    public List<Evt> selectEvtList(Evt evt) {
        return evtMapper.selectEvtList(evt);
    }

    /**
     * 新增事件管理
     *
     * @param evt 事件管理
     * @return 结果
     */
    @Override
    public int insertEvt(Evt evt) {
        return evtMapper.insertEvt(evt);
    }

    /**
     * 修改事件管理
     *
     * @param evt 事件管理
     * @return 结果
     */
    @Override
    public int updateEvt(Evt evt) {
        return evtMapper.updateEvt(evt);
    }

    /**
     * 批量删除事件管理
     *
     * @param ids 需要删除的事件管理主键
     * @return 结果
     */
    @Override
    public int deleteEvtByIds(String ids) {
        return evtMapper.deleteEvtByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除事件管理信息
     *
     * @param id 事件管理主键
     * @return 结果
     */
    @Override
    public int deleteEvtById(Long id) {
        return evtMapper.deleteEvtById(id);
    }

    @Override
    public boolean checkBhUnique(Evt evt) {
        Evt info = evtMapper.checkBhUnique(evt.getBh());
        if (StringUtils.isNotNull(info)) {
            if (StringUtils.isNull(evt.getId()) || info.getId().longValue() != evt.getId()) {
                return UserConstants.NOT_UNIQUE;
            }
        }
        return UserConstants.UNIQUE;
    }

    @Override
    public String importEvt(List<Evt> evtList, boolean isUpdateSupport, Long opUserId) {
        if (StringUtils.isNull(evtList) || evtList.size() == 0) {
            throw new ServiceException("导入数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        List<Evt> evtListNew = new ArrayList<>();
        for (Evt evt : evtList) {
            try {
                //tag
                if (StringUtils.isNotEmpty(evt.getTag().getDictLabel())) {
                    SysDictData sysDictDataSp = new SysDictData();
                    sysDictDataSp.setDictType(DictConstants.evt_tag);
                    sysDictDataSp.setDictLabel(evt.getTag().getDictLabel().trim());
                    List<SysDictData> dictDataList = dictDataMapper.selectDictDataByLabel(sysDictDataSp);
                    if (dictDataList.size() > 0) {
                        evt.setTagId(Long.parseLong(dictDataList.get(0).getDictValue()));
                    } else {
                        sysDictDataSp = new SysDictData();
                        sysDictDataSp.setDictType(DictConstants.evt_tag);
                        Long nextValue = dictDataMapper.getMaxValueLong(sysDictDataSp) + 1;
                        Long nextSort = dictDataMapper.getMaxSort(sysDictDataSp) + 1;

                        SysDictData newSysDictData = new SysDictData();
                        newSysDictData.setDictSort(nextSort);
                        newSysDictData.setDictType(DictConstants.evt_tag);
                        newSysDictData.setDictValue((nextValue) + "");
                        newSysDictData.setDictLabel(evt.getTag().getDictLabel().trim());
                        newSysDictData.setStatus(UserConstants.DICT_NORMAL);
                        newSysDictData.setCreateTime(new Date());
                        sysDictDataService.insertDictData(newSysDictData);

                        evt.setTagId(nextValue);
                    }
                }
                //source
                if (StringUtils.isNotEmpty(evt.getSource().getDictLabel())) {
                    SysDictData sysDictDataSp = new SysDictData();
                    sysDictDataSp.setDictType(DictConstants.evt_source);
                    sysDictDataSp.setDictLabel(evt.getSource().getDictLabel().trim());
                    List<SysDictData> dictDataList = dictDataMapper.selectDictDataByLabel(sysDictDataSp);
                    if (dictDataList.size() > 0) {
                        evt.setSourceId(Long.parseLong(dictDataList.get(0).getDictValue()));
                    } else {
                        sysDictDataSp = new SysDictData();
                        sysDictDataSp.setDictType(DictConstants.evt_source);
                        Long nextValue = dictDataMapper.getMaxValueLong(sysDictDataSp) + 1;
                        Long nextSort = dictDataMapper.getMaxSort(sysDictDataSp) + 1;

                        SysDictData newSysDictData = new SysDictData();
                        newSysDictData.setDictSort(nextSort);
                        newSysDictData.setDictType(DictConstants.evt_tag);
                        newSysDictData.setDictValue((nextValue) + "");
                        newSysDictData.setDictLabel(evt.getTag().getDictLabel().trim());
                        newSysDictData.setStatus(UserConstants.DICT_NORMAL);
                        newSysDictData.setCreateTime(new Date());
                        sysDictDataService.insertDictData(newSysDictData);
                        evt.setSourceId(nextValue);
                    }
                }

                //evt_type
                if (StringUtils.isEmpty(evt.getEvtType1().getTypeName())) {
                    throw new Exception("一级分类为空");
                }
                if (StringUtils.isEmpty(evt.getEvtType2().getTypeName())) {
                    throw new Exception("二级分类为空");
                }
                List<Long> evtTypeIds = evtTypeService.getOrAddByTypeNames(evt.getEvtType1().getTypeName(), evt.getEvtType2().getTypeName(), evt.getEvtType3().getTypeName());
                evt.setEvtTypeId1(evtTypeIds.get(0));
                evt.setEvtTypeId2(evtTypeIds.get(1));
                if (StringUtils.isNotEmpty(evt.getEvtType3().getTypeName())) {
                    evt.setEvtTypeId3(evtTypeIds.get(2));
                }

                //owner dept
                if (StringUtils.isEmpty(evt.getOwnerDept().getDeptName())) {
                    throw new Exception("所属部门为空");
                }
                SysDept dept = sysDeptService.selectDeptByName(evt.getOwnerDept().getDeptName());
                if (dept == null) {
                    Long nextSort = sysDeptService.getMaxSort() + 1;

                    dept = new SysDept();
                    dept.setParentId(100l);
                    dept.setAncestors("0,100");
                    dept.setDeptName(evt.getOwnerDept().getDeptName());
                    dept.setOrderNum(nextSort);
                    dept.setStatus(UserConstants.DICT_NORMAL);
                    dept.setDelFlag(UserConstants.DICT_NORMAL);
                    dept.setCreateTime(new Date());
                    sysDeptService.insertDept(dept);
                }
                evt.setOwnerDeptId(dept.getDeptId());

                // 验证是否存在编号
                Evt dbEvt = evtMapper.selectEvtByBh(evt.getBh());
                if (StringUtils.isNull(dbEvt)) {
//                    BeanValidators.validateWithException(validator, evt);
                    evt.setAddUserId(opUserId);
                    evt.setAddTime(new Date());
                    /*evtMapper.insertEvt(evt);*/
                    evtListNew.add(evt);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、编号 " + evt.getBh() + " 导入成功");
                } else {
//                    BeanValidators.validateWithException(validator, evt);
                    evt.setId(dbEvt.getId());
                    evt.setUpdateUserId(opUserId);
                    evt.setUpdateTime(new Date());
                    evtMapper.updateEvt(evt);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、编号 " + evt.getBh() + " 更新成功");
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、编号 " + evt.getBh() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }
        }
        int size = evtListNew.size();
        if (size > 0) {
            int batchSize = 1000; // 设定批处理的大小
            for (int i = 0; i < size; i += batchSize) {
                List<Evt> batchList = evtListNew.subList(i, Math.min(i + batchSize, size));
                evtMapper.insertEvtBatch(batchList);
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    // type: 总量-sum, 按事件类型-evt_type
    // period: 日-day, 月-month, 年-year
    @Override
    public Map selectEchartsEvtDataset(String type, String period) {
        Map map = new HashMap();

        EchartsDataset dataset = new EchartsDataset();
        List<Map> series = new ArrayList<>();

        List<EvtType> allEvtTypeList = null;
        //dimensions
        List<String> dimensions = new ArrayList<>();
        dimensions.add("product");
        if ("evt_type".equals(type)) {
            EvtType spEvtType = new EvtType();
            spEvtType.setParentId(0l);
            spEvtType.setStatus(UserConstants.EVT_TYPE_NORMAL);
            allEvtTypeList = evtTypeService.selectEvtTypeList(spEvtType);
            for (EvtType evtType : allEvtTypeList) {
                dimensions.add(evtType.getTypeName());
                Map serie = new HashMap();
                serie.put("type", "bar");
                serie.put("barGap", 0);
                series.add(serie);
            }
        } else {
            dimensions.add("总量");
            Map serie = new HashMap();
            serie.put("type", "bar");
            serie.put("barGap", 0);
            series.add(serie);
        }
        dataset.setDimensions(dimensions);


        //查询数据
        Map spMap = new HashMap();
        if ("evt_type".equals(type)) {
            //按事件类型
            spMap.put("groupByTypeId", "1");
        }
        if ("day".equals(period)) {
            //日--最近30日
            spMap.put("groupByReportTimeFormat", "%m月%d日");
            spMap.put("reportTimeStart", new SimpleDateFormat("yyyy-MM-dd").format(DateUtils.addDays(new Date(), -30)));
        } else if ("month".equals(period)) {
            //月-最近一年
            spMap.put("groupByReportTimeFormat", "%y年%m月");
            spMap.put("reportTimeStart", new SimpleDateFormat("yyyy-MM-dd").format(DateUtils.setDays(DateUtils.addYears(new Date(), -1), 1)));
        } else if ("year".equals(period)) {
            //年，10年前
            spMap.put("groupByReportTimeFormat", "%y年");
            spMap.put("reportTimeStart", new SimpleDateFormat("yyyy-MM-dd").format(DateUtils.setMonths(DateUtils.setDays(DateUtils.addYears(new Date(), -10), 1), 0)));
        }
        List<Map> lst = evtMapper.selectEchartsEvtDataset(spMap);

        //source
        List<Map> source = new ArrayList<>();
        if ("day".equals(period)) {
            //日--最近30日
            for (int i = 30; i >= 0; i--) {
                Map m = new HashMap<>();
                String dtStr = new SimpleDateFormat("MM月dd日").format(DateUtils.addDays(new Date(), -i));
                m.put("product", dtStr);
                if ("evt_type".equals(type)) {
                    for (EvtType evtType : allEvtTypeList) {
                        int cnt = getEvtCnt(lst, dtStr, evtType.getTypeId());
                        m.put(evtType.getTypeName(), cnt);
                    }
                } else {
                    int cnt = getEvtCnt(lst, dtStr, null);
                    m.put(dtStr, cnt);
                }
                source.add(m);
            }
        } else if ("month".equals(period)) {
            //月-最近一年
            for (int i = 12; i >= 0; i--) {
                Map m = new HashMap<>();
                String dtStr = new SimpleDateFormat("yy年MM月").format(DateUtils.addMonths(new Date(), -i));
                m.put("product", dtStr);
                if ("evt_type".equals(type)) {
                    for (EvtType evtType : allEvtTypeList) {
                        int cnt = getEvtCnt(lst, dtStr, evtType.getTypeId());
                        m.put(evtType.getTypeName(), cnt);
                    }
                } else {
                    int cnt = getEvtCnt(lst, dtStr, null);
                    m.put(dtStr, cnt);
                }
                source.add(m);
            }
        } else if ("year".equals(period)) {
            //月-最近一年
            for (int i = 10; i >= 0; i--) {
                Map m = new HashMap<>();
                String dtStr = new SimpleDateFormat("yy年").format(DateUtils.addYears(new Date(), -i));
                m.put("product", dtStr);
                if ("evt_type".equals(type)) {
                    for (EvtType evtType : allEvtTypeList) {
                        int cnt = getEvtCnt(lst, dtStr, evtType.getTypeId());
                        m.put(evtType.getTypeName(), cnt);
                    }
                } else {
                    int cnt = getEvtCnt(lst, dtStr, null);
                    m.put(dtStr, cnt);
                }
                source.add(m);
            }
        }
        dataset.setSource(source);

        map.put("dataset", dataset);
        map.put("series", series);

        return map;
    }

    private int getEvtCnt(List<Map> lst, String dtStr, Long typeId) {
        for (Map map : lst) {
            if (dtStr.equals(map.get("dt")) && (typeId == null || typeId.longValue() == Long.valueOf(map.get("type1").toString()))) {
                return Integer.valueOf(map.get("cnt").toString());
            }
        }
        return 0;
    }
}
